package com.example.security.assembly;

import com.example.base.dto.TokenUserDTO;
import com.example.base.utils.RedisUtil;
import com.example.sys.dto.req.UserLoginReq;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import java.util.Collection;
import java.util.List;
import java.util.Objects;

@Slf4j
public class UserPostLoginAuthenticationToken extends AbstractAuthenticationToken {

    private static final String USER_ROLE_PER = "user:role:";

    // 一般是用户名
    private final Object principal;

    //一般是密码
    private Object credentials;

    //根据token解析的用户信息
    @Getter
    private TokenUserDTO user;

    public UserPostLoginAuthenticationToken(Object principal, Object credentials) {
        super(null);
        this.principal = principal;
        this.credentials = credentials;
        this.setAuthenticated(false);
    }

    public UserPostLoginAuthenticationToken(Object principal, Object credentials, TokenUserDTO user) {
        super(null);
        this.principal = principal;
        this.credentials = credentials;
        this.user = user;
        //已经登录过 这里要为true
        this.setAuthenticated(true);
    }

    public UserPostLoginAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true);
    }

    @Override
    public Object getCredentials() {
        return this.credentials;
    }

    @Override
    public Object getPrincipal() {
        return this.principal;
    }

    /**
     * 登录时构建的token
     * @param loginReq
     * @return
     */
    public static UserPostLoginAuthenticationToken unauthenticated(UserLoginReq loginReq) {
        return new UserPostLoginAuthenticationToken(loginReq.getLoginName(), loginReq.getPassword());
    }

    /**
     * 授权后构建token
     * @param principal
     * @param credentials
     * @param authorities
     * @return
     */
    public static UserPostLoginAuthenticationToken authenticated(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        return new UserPostLoginAuthenticationToken(principal, credentials, authorities);
    }

    /**
     * 已经登录过 使用前端传递的token构建 UserPostLoginAuthenticationToken
     * 通知将用户角色设置到token中
     * @param tokenUserDTO
     * @return
     */
    public static UserPostLoginAuthenticationToken authenticated(TokenUserDTO tokenUserDTO) {
        UserPostLoginAuthenticationToken token = new UserPostLoginAuthenticationToken(tokenUserDTO.getUserName(), null, tokenUserDTO);
        ArrayNode arrayNode = RedisUtil.getValue(USER_ROLE_PER + tokenUserDTO.getUserId(), ArrayNode.class);
        if (Objects.nonNull(arrayNode)){
            List<String> roleList = Lists.newArrayList();
            for (JsonNode node : arrayNode) {
                roleList.add(node.textValue());
                SimpleGrantedAuthority authority = new SimpleGrantedAuthority(node.textValue());
                token.getAuthorities().add(authority);
            }
            tokenUserDTO.setRoleCodeList(roleList);
        }
        return token;
    }
}
